<?php
declare (strict_types=1);

namespace app;

use app\admin\common\Lunar;
use app\admin\controller\traits\BaseAction;
use app\admin\library\Auth;
use app\admin\model\FlowNumber;
use app\admin\model\WorkFlows;
use app\middleware\CheckLogin;
use fast\Tree;
use think\App;
use think\Config;
use think\Container;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\facade\Route;
use think\facade\Session;
use think\facade\View;
use think\Hook;
use think\Loader;
use think\Response;
use think\Validate;
use workflow\workflow;

/**
 * 控制器基础类
 */
abstract class BaseController
{
//
    protected $middleware = [CheckLogin::class];
    /**
     * Request实例
     * @var \think\Request
     */
    protected $request;

    protected $noNeedLogin = [];

    /**
     * 无需鉴权的方法,但需要登录
     * @var array
     */
    protected $noNeedRight = [];
    /**
     * 应用实例
     * @var \think\App
     */
    protected $app;

    /**
     * 是否开启数据限制
     * 支持auth/personal
     * 表示按权限判断/仅限个人
     * 默认为禁用,若启用请务必保证表中存在admin_id字段
     */
    protected $dataLimit = false;


    /**
     * 是否是关联查询
     */
    protected $relationSearch = false;
    /**
     * 是否开启Validate验证
     */
    protected $modelValidate = false;

    /**
     * 是否开启模型场景验证
     */
    protected $modelSceneValidate = false;


    /**
     * 数据限制字段
     */
    protected $dataLimitField = 'admin_id';


    /**
     * 数据限制开启时自动填充限制字段值
     */
    protected $dataLimitFieldAutoFill = true;
    /**
     * 是否批量验证
     * @var bool
     */
    protected $batchValidate = false;


    /**
     * Selectpage可显示的字段
     */
    protected $selectpageFields = '*';


    /**
     * 权限控制类
     * @var Auth
     */
    protected $auth = null;

    protected $user = null;

    protected $lunar = null;

    protected $work = null;

    //定义常量，各个需要下拉选择的表字段
    const CATPATHKEY = [
        'catPathKey' => '店铺类型',
        'isChainStore' => '直营或加盟',
        'floor' => '所处楼层',
        'wall' => '是否有店面柱墙',
        'angle' => '是否有死角',
        'decoration_style' => '装修风格',
        'allowed' => '店门是否允许外开',
        'payment' => '支付方式',
        'business_circle_level' => '商圈级别',
        'is_metro' => '有无地铁',
        'road_is_unobstructed' => '主干道是否通畅',
        'sidewalk_is_unobstructed' => '人行道是否通畅',
        'hasTakeaway' => '是否外卖',
        'hasBooking' => '是否可以预约',

    ];

    /**
     * 构造方法
     * @access public
     * @param App $app 应用对象
     */
    public function __construct(App $app)
    {
        $this->app = $app;
        $this->request = $this->app->request;
        // 控制器初始化
        $this->initialize();
    }

    // 初始化
    protected function initialize()
    {
        $modulename = \think\facade\Request::action();
        $controllername = parse_name(\think\facade\Request::controller());
        $actionname = strtolower(\think\facade\Request::action());
        $path = 'home/' . $actionname;

        $this->auth = Auth::instance();
        $this->lunar = new Lunar();
        $this->work = new workflow();
        $this->user = Session::get('admin');
        // 设置当前请求的URI
        $this->auth->setRequestUri($path);
        if (!$this->auth->match($this->noNeedLogin)) {
            //检测是否登录
            if (!$this->auth->isLogin()) {
                $url = Session::get('referer');
                $url = $url ? $url : $this->request->url();
                if ($url == '/') {
                    return redirect('index/login', 302);
                }
                return redirect('index/login', 302);
//                $this->error(('Please login first'), url('index/login', ['url' => $url]));
            }
//            // 判断是否需要验证权限
//            if (!$this->auth->match($this->noNeedRight)) {
//                // 判断控制器和方法判断是否有对应权限
//                if (!$this->auth->check($path)) {
//                    echo "没有权限";
//                    exit();
//                }
//            }
        }
        // 非选项卡时重定向
        if (!$this->request->isPost()) {

            $url = preg_replace_callback("/([\?|&]+)ref=addtabs(&?)/i", function ($matches) {
                return $matches[2] == '&' ? $matches[1] : '';
            }, $this->request->url());
            if (\think\facade\Config::get('url_domain_deploy')) {
                if (stripos($url, $this->request->server('SCRIPT_NAME')) === 0) {
                    $url = substr($url, strlen($this->request->server('SCRIPT_NAME')));
                }
                $url = url($url, '', false);
            }

            redirect('index/index', 302);
        }

        View::assign('auth', $this->auth);
        View::assign('admin', Session::get('admin'));
    }

    /**
     * 验证数据
     * @access protected
     * @param array $data 数据
     * @param string|array $validate 验证器名或者验证规则数组
     * @param array $message 提示信息
     * @param bool $batch 是否批量验证
     * @return array|string|true
     * @throws ValidateException
     */
    protected function validate(array $data, $validate, array $message = [], bool $batch = false)
    {
        if (is_array($validate)) {
            $v = new Validate();
            $v->rule($validate);
        } else {
            if (strpos($validate, '.')) {
                // 支持场景
                list($validate, $scene) = explode('.', $validate);
            }
            $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
            $v = new $class();
            if (!empty($scene)) {
                $v->scene($scene);
            }
        }

        $v->message($message);

        // 是否批量验证
        if ($batch || $this->batchValidate) {
            $v->batch(true);
        }

        return $v->failException(true)->check($data);
    }

    /**
     * 操作成功跳转的快捷方法
     * @access protected
     * @param mixed $msg 提示信息
     * @param string $url 跳转的URL地址
     * @param mixed $data 返回的数据
     * @param integer $wait 跳转等待时间
     * @param array $header 发送的Header信息
     * @return void
     */
    protected function success($msg = '', string $url = null, $data = '', int $wait = 3, array $header = [])
    {
        if (is_null($url) && isset($_SERVER["HTTP_REFERER"])) {
            $url = $_SERVER["HTTP_REFERER"];
        } elseif ($url) {
            $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : $this->app->route->buildUrl($url);
        }
        $result = [
            'code' => 1,
            'msg' => $msg,
            'data' => $data,
            'url' => $url,
            'wait' => $wait,
        ];
        $type = $this->getResponseType();
        // 把跳转模板的渲染下沉，这样在 response_send 行为里通过getData()获得的数据是一致性的格式
        if ('html' == strtolower($type)) {
            $type = 'view';
        }
        $response = Response::create($result, $type)->header($header)->options(['jump_template' => app()->config->get('app.dispatch_success_tmpl')]);
        throw new HttpResponseException($response);
    }

    /**
     * 操作错误跳转的快捷方法
     * @access protected
     * @param mixed $msg 提示信息
     * @param string $url 跳转的URL地址
     * @param mixed $data 返回的数据
     * @param integer $wait 跳转等待时间
     * @param array $header 发送的Header信息
     * @return void
     */
    protected function error($msg = '', string $url = null, $data = '', int $wait = 3, array $header = [])
    {
        if (is_null($url)) {
            $url = $this->request->isAjax() ? '' : 'javascript:history.back(-1);';
        } elseif ($url) {
            $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : $this->app->route->buildUrl($url);
        }
        $result = [
            'code' => 0,
            'msg' => $msg,
            'data' => $data,
            'url' => $url,
            'wait' => $wait,
        ];
        $type = $this->getResponseType();
        if ('html' == strtolower($type)) {
            $type = 'view';
        }
        $response = Response::create($result, $type)->header($header)->options(['jump_template' => app()->config->get('jump.dispatch_error_tmpl')]);
        throw new HttpResponseException($response);
    }


    protected function getResponseType()
    {

        if (!$this->app) {
            $this->app = Container::get('app');
        }
        $isAjax = $this->app['request']->isAjax();
        $config = $this->app['config'];
        return $isAjax ? $config->get('app.default_ajax_return') : $config->get('app.default_return_type');
    }

    /**
     * 获取数据限制的管理员ID
     * 禁用数据限制时返回的是null
     * @return mixed
     */
    protected function getDataLimitAdminIds()
    {
        if (!$this->dataLimit) {
            return null;
        }
        if ($this->auth->isSuperAdmin()) {
            return null;
        }
        $adminIds = [];
        if (in_array($this->dataLimit, ['auth', 'personal'])) {
            $adminIds = $this->dataLimit == 'auth' ? $this->auth->getChildrenAdminIds(true) : [$this->auth->id];
        }
        return $adminIds;
    }

    /**
     * 前台提交过来,需要排除的字段数据
     */
    protected $excludeFields = "";

    /**
     * 排除前台提交过来的字段
     * @param $params
     * @return array
     */
    protected function preExcludeFields($params)
    {
        if (is_array($this->excludeFields)) {
            foreach ($this->excludeFields as $field) {
                if (key_exists($field, $params)) {
                    unset($params[$field]);
                }
            }
        } else {
            if (key_exists($this->excludeFields, $params)) {
                unset($params[$this->excludeFields]);
            }
        }
        return $params;
    }

    /**
     * 获取流水号
     */
    public function getnumber($code)
    {
        $row = FlowNumber::where(['code' => $code])->find();

        if (!$row) {
            return time();
        }
        $serial_no = '';
        $serial_no .= $row['pre'];
        if ($row['year'] == 1) {

            $serial_no .= Date('Y');
        }
        if ($row['month'] == 1) {
            $serial_no .= Date('m');
        }

        $serial_no .= str_pad((string)$row['index'], $row['lengh'], "0", STR_PAD_LEFT);

        $row->save(['index' => ($row['index'] + 1)]);
        return $serial_no;
    }

}
